Skip to content

Switch CI to hardened runners with JFrog OIDC authentication#753

Open
mihaimitrea-db wants to merge 10 commits intomainfrom
mihaimitrea-db/jfrog-artifactory-migration
Open

Switch CI to hardened runners with JFrog OIDC authentication#753
mihaimitrea-db wants to merge 10 commits intomainfrom
mihaimitrea-db/jfrog-artifactory-migration

Conversation

@mihaimitrea-db
Copy link
Copy Markdown
Contributor

@mihaimitrea-db mihaimitrea-db commented Apr 7, 2026

Summary

Route Maven dependency resolution through JFrog Artifactory on hardened runners that block direct access to Maven Central. Authenticate via GitHub Actions OIDC (zero stored secrets).

Modeled after the CLI (#4875), Go SDK (#1609), and Python SDK (#1379).

What changed

  • New composite action (.github/actions/setup-build-environment/action.yml): Sets up JFrog CLI via OIDC, installs the JDK, and generates a ~/.m2/settings.xml that mirrors all Maven repositories through JFrog (db-maven). Skipped on macOS (not hardened).
  • push.yml: Added workflow-level id-token: write permission for OIDC. Switched fmt, unit-tests (Linux), and check-lock jobs to databricks-protected-runner-group. macOS tests remain on public runners. Used matrix include to map OS strings to runner configs, preserving the original check names for branch protection compatibility.
  • Makefile: Added fix-lockfile target.
  • lockfile.json: Regenerated to pick up commons-configuration2 2.13.0 (was out of date since PR Bump commons-configuration2 from 2.11.0 to 2.13.0 #743 bumped the POM without regenerating the lockfile).

Why settings.xml is needed

Hardened runners terminate SSL handshakes to repo.maven.apache.org. Unlike Go (GOPROXY env var) or Python (UV_INDEX_URL), Maven has no environment variable to redirect repository access. The standard mechanism is a ~/.m2/settings.xml with a <mirror> entry that routes all repository requests through JFrog.

The lockfile problem

Maven's lockfile.json stores the full download URL in each dependency's resolved field. When Maven resolves through JFrog, these become https://databricks.jfrog.io/artifactory/db-maven/... instead of https://repo.maven.apache.org/maven2/.... If someone runs make lock while Maven is routed through JFrog (CI, VPN), the lockfile would contain proxy URLs that shouldn't be committed.

make fix-lockfile

Replaces JFrog proxy URLs with their public Maven Central equivalents in all lockfile.json files. Prevents proxy URLs from being accidentally committed.

When to use it: Run make fix-lockfile before committing if you regenerated the lockfile while Maven was routing through JFrog.

CI enforcement: The fmt job runs make fix-lockfile followed by git diff --exit-code, so any committed proxy URLs will fail CI.

Cache ordering

The Maven cache (~/.m2/repository) must be restored before the composite action runs. The composite action generates ~/.m2/settings.xml with a fresh OIDC token. If the cache step runs after and restores ~/.m2 (including a stale settings.xml from a previous run), the expired token causes 401 errors. Caching only ~/.m2/repository (not all of ~/.m2) prevents this.

Out of scope

  • release.yml: Publishes to Maven Central via Sonatype. Needs special publish runners per the migration guide. Separate follow-up with the security team.
  • tagging.yml: Generated from Universe (openapi/genkit/sync/workflows/tagging.yml). JFrog setup needs to be upstreamed to the genkit template.
  • conftest.yml: Only downloads conftest binary from GitHub Releases (not Maven). Can stay on ubuntu-latest.

Test plan

  • Verify mvn --errors spotless:check passes (fmt job)
  • Verify mvn --errors test passes on Linux (Java 8, 11, 17, 20)
  • Verify mvn --errors test passes on macOS (Java 8, 11, 17, 20)
  • Verify make check-lock passes (lockfile validation)
  • Verify conftest passes on the new workflow files
  • Verify check names match branch protection rules

NO_CHANGELOG=true

Route Maven dependency resolution through JFrog Artifactory on hardened
runners that block direct access to Maven Central. Authenticate via
GitHub Actions OIDC (zero stored secrets).

- Add composite action for JFrog OIDC + Java setup
- Switch fmt, unit-tests (Linux), and check-lock to
  databricks-protected-runner-group
- Add workflow-level id-token: write permission for OIDC
- Keep macOS unit-tests on public runners (not hardened)

NO_CHANGELOG=true
Hardened runners terminate SSL handshakes to repo.maven.apache.org,
so Maven needs an explicit mirror pointing to JFrog Artifactory.
Generate ~/.m2/settings.xml with OIDC credentials from the JFrog
setup step.
When lockfiles are regenerated while Maven resolves through JFrog
(CI or VPN), the resolved URLs point to databricks.jfrog.io instead
of repo.maven.apache.org. This target rewrites them back to public
Maven Central URLs before committing.
Run make fix-lockfile in the fmt job and fail on git diff, catching
any accidentally committed JFrog proxy URLs in lockfile.json. Same
CI enforcement pattern as the Python SDK.
The lockfile is out of date on main (commons-configuration2 2.11.0 vs
2.13.0 in POM). This temporary job regenerates it through JFrog and
normalizes URLs back to Maven Central. The check-lock job now depends
on it so it validates the freshly generated lockfile.

Remove this job once the lockfile is up to date.
The actions/cache step was restoring ~/.m2 (including settings.xml
from a previous run with an expired OIDC token) after the composite
action generated a fresh settings.xml. This caused 401 errors on
subsequent runs.

Fix by:
1. Caching only ~/.m2/repository (artifacts only, not settings.xml)
2. Moving cache restore before the build environment setup
The lockfile has been regenerated and committed. Remove the temporary
job and restore check-lock to run independently with the same cache
and build environment setup as other jobs.
Use matrix include to map os strings to runner configs instead of
restructuring the matrix with object values. This keeps the auto-
generated check names (e.g. unit-tests (ubuntu-latest, 8)) matching
what branch protection rules expect.
@mihaimitrea-db mihaimitrea-db deployed to test-trigger-is April 7, 2026 13:35 — with GitHub Actions Active
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 7, 2026

If integration tests don't run automatically, an authorized user can run them manually by following the instructions below:

Trigger:
go/deco-tests-run/sdk-java

Inputs:

  • PR number: 753
  • Commit SHA: 3393aa4283345bc67a13d521f5f4bca58f1088dc

Checks will be approved automatically on success.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants